from typing import Dict, List, Optional
import pandas as pd
import numpy as np
from datetime import datetime
from decimal import Decimal

from .trading_strategy import TradingStrategy
from analysis.market_analyzer import MarketAnalyzer
from analysis.technical_indicators import TechnicalIndicators
from analysis.ml_predictor import MLPredictor
from risk.risk_manager import RiskManager
from backtest.event import MarketEvent, SignalEvent  # 修正导入路径

'''机器学习增强型交易策略'''
class MLEnhancedStrategy(TradingStrategy):
    """机器学习增强型交易策略"""
    
    def __init__(
        self,
        market_analyzer: MarketAnalyzer,
        risk_manager: RiskManager,
        technical_indicators: TechnicalIndicators,
        ml_predictor: MLPredictor,
        chain_analyzer=None,  # 可选参数
        sentiment_analyzer=None,  # 可选参数
        config: Dict = None
    ):
        """
        初始化策略
        
        Args:
            market_analyzer: 市场分析器
            risk_manager: 风险管理器
            technical_indicators: 技术指标分析器
            ml_predictor: 机器学习预测器
            chain_analyzer: 链上数据分析器（可选）
            sentiment_analyzer: 情感分析器（可选）
            config: 策略配置
        """
        super().__init__(market_analyzer, risk_manager)
        self.technical_indicators = technical_indicators
        self.ml_predictor = ml_predictor
        self.chain_analyzer = chain_analyzer
        self.sentiment_analyzer = sentiment_analyzer
        self.config = config or {
            'position_size': 0.1,  # 每次交易的仓位大小
            'stop_loss': 0.02,     # 止损比例
            'take_profit': 0.05,   # 止盈比例
            'max_positions': 3,    # 最大持仓数量
            'min_confidence': 0.6  # 最小置信度
        }
        
    def analyze_market(self, market_data):
        """
        分析市场数据，生成交易信号
        """
        try:
            # 如果输入已经是DataFrame，直接使用
            if isinstance(market_data, pd.DataFrame):
                df = market_data.copy()
            else:
                # 否则转换为DataFrame
                df = pd.DataFrame(market_data)
            
            print("Initial columns:", df.columns.tolist())
            
            # 计算技术指标
            df = self.technical_indicators.calculate_all(df)
            print("Columns after technical indicators:", df.columns.tolist())
            
            # 获取技术指标信号
            tech_signals = self.technical_indicators.get_signal_summary(df)
            
            # 使用ML预测
            ml_signals = self.ml_predictor.predict(df)
            
            # 合并信号
            signals = {
                'technical': tech_signals,
                'ml': ml_signals
            }
            
            return signals
            
        except Exception as e:
            print(f"分析市场数据时出错: {str(e)}")
            raise
        
    def generate_signals(self, analysis: Dict) -> Dict[str, str]:
        """
        生成交易信号
        
        Args:
            analysis: 市场分析结果
            
        Returns:
            交易信号
        """
        tech_signals = analysis['technical']
        ml_predictions = analysis['ml_predictions']
        
        # 技术面评分
        tech_score = 0
        
        # 趋势信号评分
        if tech_signals.get('trend_signals', {}).get('macd_trend') == 'bullish':
            tech_score += 1
        if tech_signals.get('trend_signals', {}).get('ema_trend') == 'bullish':
            tech_score += 1
        if tech_signals.get('trend_signals', {}).get('supertrend') == 'bullish':
            tech_score += 1
            
        # 动量信号评分
        if tech_signals.get('momentum_signals', {}).get('rsi') == 'buy':
            tech_score += 1
        if tech_signals.get('momentum_signals', {}).get('stoch') == 'buy':
            tech_score += 1
            
        # 波动信号评分
        if tech_signals.get('volatility_signals', {}).get('bbands') == 'buy':
            tech_score += 1
        if tech_signals.get('volatility_signals', {}).get('atr') == 'low':
            tech_score += 0.5
            
        # ML预测评分
        ml_score = ml_predictions.get('probability', 0)
        
        # 链上数据评分
        chain_score = 0
        if 'chain' in analysis and analysis['chain']:
            chain_data = analysis['chain']
            if chain_data.get('whale_activity') == 'accumulating':
                chain_score += 1
            if chain_data.get('network_growth') == 'positive':
                chain_score += 1
                
        # 情感分析评分
        sentiment_score = 0
        if 'sentiment' in analysis and analysis['sentiment']:
            sentiment_data = analysis['sentiment']
            if sentiment_data.get('overall_sentiment') > 0.6:
                sentiment_score += 1
            if sentiment_data.get('news_sentiment') > 0.6:
                sentiment_score += 1
        
        # 计算总分
        total_signals = 3  # 技术分析、ML预测、链上数据
        total_score = (tech_score / 6.5) * 0.4  # 技术分析权重40%
        total_score += ml_score * 0.4  # ML预测权重40%
        
        if chain_score > 0:
            total_score += (chain_score / 2) * 0.1  # 链上数据权重10%
        if sentiment_score > 0:
            total_score += (sentiment_score / 2) * 0.1  # 情感分析权重10%
        
        # 生成信号
        signal = {
            'type': 'buy' if total_score > self.config['min_confidence'] else 'hold',
            'confidence': total_score,
            'timestamp': datetime.now(),
            'scores': {
                'technical': tech_score / 6.5,
                'ml': ml_score,
                'chain': chain_score / 2 if chain_score > 0 else None,
                'sentiment': sentiment_score / 2 if sentiment_score > 0 else None
            }
        }
        
        return signal
        
    def calculate_signals(self, event: MarketEvent) -> List[SignalEvent]:
        """
        根据市场事件计算交易信号
        """
        try:
            # 获取市场数据
            market_data = event.data
            
            # 确保market_data是DataFrame类型
            if not isinstance(market_data, pd.DataFrame):
                df = pd.DataFrame.from_dict(market_data, orient='index')
                df.index = pd.to_datetime(df.index)
            else:
                df = market_data
            
            print("Market data columns:", df.columns.tolist())
            
            # 分析市场数据
            analysis = self.analyze_market(df)
            
            # 生成交易信号
            signals = []
            
            # 如果有技术分析信号
            if 'technical' in analysis:
                tech_signals = analysis['technical']
                print("Technical signals:", tech_signals)
                
                # 获取当前价格
                current_price = Decimal(str(df['close'].iloc[-1]))
                
                # MACD趋势信号
                if tech_signals.get('macd_trend') == 'bullish':
                    signal = SignalEvent(
                        timestamp=event.timestamp,
                        type='SIGNAL',
                        exchange=event.exchange,
                        symbol=event.symbol,
                        signal_type='entry',
                        side='long',
                        price=current_price,
                        strength=1.0
                    )
                    signals.append(signal)
                elif tech_signals.get('macd_trend') == 'bearish':
                    signal = SignalEvent(
                        timestamp=event.timestamp,
                        type='SIGNAL',
                        exchange=event.exchange,
                        symbol=event.symbol,
                        signal_type='entry',
                        side='short',
                        price=current_price,
                        strength=1.0
                    )
                    signals.append(signal)
            
            return signals
            
        except Exception as e:
            print(f"计算信号时出错: {str(e)}")
            raise
        
    def calculate_position_size(self, signal: Dict) -> float:
        """
        计算仓位大小
        
        Args:
            signal: 交易信号
            
        Returns:
            仓位大小
        """
        base_size = self.config['position_size']
        confidence = signal['confidence']
        
        # 根据置信度调整仓位
        position_size = base_size * confidence
        
        # 检查风险限制
        position_size = self.risk_manager.adjust_position_size(position_size)
        
        return position_size
        
    def execute_trade(self, signal: Dict, market_data: pd.DataFrame):
        """
        执行交易
        
        Args:
            signal: 交易信号
            market_data: 市场数据
        """
        if signal['type'] == 'hold':
            return
            
        # 检查当前持仓
        current_positions = len(self.risk_manager.positions)
        if current_positions >= self.config['max_positions']:
            return
            
        # 计算仓位大小
        position_size = self.calculate_position_size(signal)
        
        # 获取当前价格
        current_price = market_data['close'].iloc[-1]
        
        if signal['type'] == 'buy':
            # 计算止损和止盈价格
            stop_loss = current_price * (1 - self.config['stop_loss'])
            take_profit = current_price * (1 + self.config['take_profit'])
            
            # 执行买入
            self.market_analyzer.place_order(
                side='buy',
                size=position_size,
                price=current_price,
                stop_loss=stop_loss,
                take_profit=take_profit
            )
        elif signal['type'] == 'sell':
            # 执行卖出
            self.market_analyzer.close_position(
                position_size=position_size,
                price=current_price
            )
            
    def update(self, market_data: pd.DataFrame):
        """
        更新策略状态
        
        Args:
            market_data: 市场数据
        """
        # 分析市场
        analysis = self.analyze_market(market_data)
        
        # 生成信号
        signal = self.generate_signals(analysis)
        
        # 执行交易
        self.execute_trade(signal, market_data)
        
        # 更新风险管理
        self.risk_manager.update_positions(market_data)
